package com.ithuameng.admin.app.system.controller;

import com.ithuameng.admin.app.system.model.Menu;
import com.ithuameng.admin.app.system.model.admin.qo.MenuQo;
import com.ithuameng.admin.app.system.model.admin.vo.MenuAddVo;
import com.ithuameng.admin.app.system.model.admin.vo.MenuEditVo;
import com.ithuameng.admin.app.system.model.admin.vo.RoleMenuVo;
import com.ithuameng.admin.app.system.model.vo.R;
import com.ithuameng.admin.app.system.service.IMenuService;
import com.ithuameng.admin.app.system.service.IRoleMenuService;
import com.ithuameng.admin.app.system.service.TreeSelect;
import com.ithuameng.admin.enums.CommonError;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * 菜单控制器
 *
 * @author ithuameng
 */
@Api(tags = "菜单控制器")
@Slf4j
@RestController
@RequestMapping("/admin/v1/menu")
public class MenuController extends AdminBaseController {

    @Resource
    private IMenuService menuService;

    @Resource
    private IRoleMenuService roleMenuService;

    @ApiOperation("获取菜单列表")
    @PreAuthorize("@ss.hasPermi('system:menu:list')")
    @GetMapping("/list")
    public R<List<Menu>> list(MenuQo menuQo, HttpServletRequest request) {
        Long userId = super.getLoginUserId(request);
        List<Menu> menus = menuService.listMenu(menuQo, userId);
        return new R<>(menus);
    }

    @ApiOperation("根据菜单编号获取详细信息")
    @PreAuthorize("@ss.hasPermi('system:menu:list')")
    @GetMapping(value = "/detail/{menuId}")
    public R<Menu> getInfo(@PathVariable Long menuId) {
        Menu menu = menuService.getById(menuId);
        if (menu == null) {
            return new R<>(CommonError.BIZ_ERR, "菜单不存在");
        }
        return new R<>(menu);
    }

    @ApiOperation("新增菜单")
    @PreAuthorize("@ss.hasPermi('system:menu:add')")
    @PostMapping("/add")
    public R<Boolean> add(@Validated @RequestBody MenuAddVo menuAddVo) {
        if (menuAddVo.getType() == null) {
            return new R<>(CommonError.BIZ_ERR, "请选择菜单类型");
        }
        if (menuAddVo.getFrame() == null) {
            return new R<>(CommonError.BIZ_ERR, "请选择是否外链");
        }
        if (menuAddVo.getDisplay() == null) {
            return new R<>(CommonError.BIZ_ERR, "请选择显示状态");
        }
        if (menuAddVo.getCache() == null) {
            return new R<>(CommonError.BIZ_ERR, "请选择是否缓存");
        }
        if (menuAddVo.getStatus() == null) {
            return new R<>(CommonError.BIZ_ERR, "请选择状态");
        }
        Menu menu = new Menu();
        try {
            BeanUtils.copyProperties(menuAddVo, menu);
            if (!menuService.checkMenuTitleUnique(menu)) {
                return new R<>(CommonError.BIZ_ERR, "菜单名称已存在");
            }
            menuService.save(menu);
            return new R<>(CommonError.OK, "添加成功");
        } catch (Exception e) {
            log.error("新增菜单失败", e);
            return new R<>(CommonError.BAD_REQUEST, "添加失败");
        }
    }

    @ApiOperation("修改菜单")
    @PreAuthorize("@ss.hasPermi('system:menu:edit')")
    @PostMapping("/edit")
    public R<Boolean> edit(@Validated @RequestBody MenuEditVo menuEditVO) {
        if (menuEditVO.getType() == null) {
            return new R<>(CommonError.BIZ_ERR, "请选择菜单类型");
        }
        if (menuEditVO.getFrame() == null) {
            return new R<>(CommonError.BIZ_ERR, "请选择是否外链");
        }
        if (menuEditVO.getDisplay() == null) {
            return new R<>(CommonError.BIZ_ERR, "请选择显示状态");
        }
        if (menuEditVO.getCache() == null) {
            return new R<>(CommonError.BIZ_ERR, "请选择是否缓存");
        }
        if (menuEditVO.getStatus() == null) {
            return new R<>(CommonError.BIZ_ERR, "请选择状态");
        }
        Menu menu = new Menu();
        try {
            BeanUtils.copyProperties(menuEditVO, menu);
            if (!menuService.checkMenuTitleUnique(menu)) {
                return new R<>(CommonError.BIZ_ERR, "菜单名称已存在");
            }
            if (menu.getId().equals(menu.getParentId())) {
                return new R<>(CommonError.BIZ_ERR, "上级菜单不能选择自己");
            }
            menuService.updateById(menu);
            return new R<>(CommonError.OK, "修改成功");
        } catch (Exception e) {
            log.error("修改菜单失败", e);
            return new R<>(CommonError.BAD_REQUEST, "修改失败");
        }
    }

    @ApiOperation("删除菜单")
    @PreAuthorize("@ss.hasPermi('system:menu:remove')")
    @PostMapping("/delete/{menuId}")
    public R<Boolean> remove(@PathVariable("menuId") Long menuId) {
        if (menuService.hasChildByMenuId(menuId)) {
            return new R<>(CommonError.BIZ_ERR, "存在子菜单,不允许删除");
        }
        if (roleMenuService.checkMenuExistRole(menuId)) {
            return new R<>(CommonError.BIZ_ERR, "菜单已分配,不允许删除");
        }
        menuService.removeById(menuId);
        return new R<>(CommonError.OK, "删除成功");
    }

    @ApiOperation("获取菜单下拉树列表")
    @GetMapping("/treeselect")
    public R<List<TreeSelect>> treeselect(MenuQo menuQo, HttpServletRequest request) {
        Long userId = super.getLoginUserId(request);
        List<Menu> menus = menuService.listMenu(menuQo, userId);
        List<TreeSelect> menuTrees = menuService.buildMenuTreeSelect(menus);
        return new R<>(menuTrees);
    }

    @ApiOperation("加载对应角色菜单列表树")
    @GetMapping(value = "/roleMenuTreeselect/{roleId}")
    public R<RoleMenuVo> roleMenuTreeselect(@PathVariable("roleId") Long roleId, HttpServletRequest request) {
        Long userId = super.getLoginUserId(request);
        List<Menu> menus = menuService.listMenu(userId);
        List<Long> checkedKeys = menuService.selectMenuListByRoleId(roleId);
        List<TreeSelect> menuTrees = menuService.buildMenuTreeSelect(menus);
        RoleMenuVo roleMenuVO = new RoleMenuVo(menuTrees, checkedKeys);
        return new R<>(roleMenuVO);
    }
}
